package ye.guo.huang.datatransferdemo.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * 	时间工具类
 */
@Slf4j
public class DateUtil {

	public static final String DATE_FORMAT = "yyyy-MM-dd";
	public static final String DATE_FORMAT_MD = "MM月dd日";
	public static final String DATE_FORMAT_HM = "HH:mm";
    public static final String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_TIME = "HH:mm:ss";
    public static final String FORMAT_DTF = "yyyy年MM月dd日 HH:mm:ss";

	public static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(FORMAT_DTF);

	public static LocalDateTime toLocalDateTime(String dateTime, String format) {
		if (StringUtils.isEmpty(dateTime)) {
			return null;
		}
		if (StringUtils.isEmpty(format)) {
			format = "yyyy-MM-dd HH:mm:ss";
		}

		DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
		LocalDateTime ldt = LocalDateTime.parse(dateTime,df);
		return ldt;
	}

	/**
	 * 	几点几分
	 * @param dateStr
	 * @return
	 */
	public static String getHourMin(String dateStr){
		return dateStr.substring(11, 17);
	}

	/**
	 * 	月日几点几分
	 * @param dateStr
	 * @return
	 */
	public static String getMonDayHourMin(String dateStr){
		return dateStr.substring(5, 17);
	}


	//改成线程安全方式
	private static ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(DATE_FORMAT);
		}
	};

	private static ThreadLocal<SimpleDateFormat> dateFormatThreadLoca = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(FORMAT_FULL);
		}
	};

	/**
	 * 	LocalDateTime 2 str
	 * @param dateTime
	 * @return
	 */
	public static String time2str(LocalDateTime dateTime){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(FORMAT_FULL);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}

	/**
	 *
	 * @param dateTime
	 * @param format
	 * @return
	 */
	public static String time2str(LocalDateTime dateTime,String format){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(format);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}

	public static String time2strymd(LocalDateTime dateTime){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_FORMAT);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}

	/**
	 * 	LocalDateTime 2 str
	 * @param dateTime
	 * @return
	 */
	public static String time2strYND(LocalDateTime dateTime){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_FORMAT);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}
	/**
	 * 	LocalDateTime 2 str
	 * @param dateTime
	 * @return
	 */
	public static String time2strMd(LocalDateTime dateTime){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_FORMAT_MD);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}

	/**
	 * 	LocalDateTime 2 str
	 * @param dateTime
	 * @return
	 */
	public static String time2strHM(LocalDateTime dateTime){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_FORMAT_HM);
		//LocalDateTime 转字符串
		String dateTimeStr = dateTime.format(pattern);
		return dateTimeStr;
	}



    /**
     * 计算2个日期之间相差多少天
     * @param start 起始日期
     * @param end 结束日期
     * @return 相差天数
     */
    public static long getDateDiff(Date start, Date end){
        long startMili = start.getTime();
        long endMili = end.getTime();
        long oneDateMili = 24 * 3600 * 1000;
        long minus = endMili - startMili;
        return minus % oneDateMili == 0 ? minus / oneDateMili : minus / oneDateMili + 1;
    }

    /**
     * 计算2个日期之间相差多少小时
     * @param start 起始日期
     * @param end 结束日期
     * @return 相差小时数
     */
    public static long getHourDiff(Date start, Date end){
        long startMili = start.getTime();
        long endMili = end.getTime();
        long oneHourMili = 3600 * 1000;
        long minus = endMili - startMili;
        return minus / oneHourMili;
    }

	// java8 date和LocalDate及LocalDateTime相互转换
    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static LocalDateTime asStringToLocalDateTime(String datetime) {
        return LocalDateTime.parse(datetime, DateTimeFormatter.ofPattern(FORMAT_FULL));
    }


    public static Date stringToDate(String dateTime) throws ParseException {
        return dateFormatThreadLoca.get().parse(dateTime);
    }

    /**
     * 把日期类型格式化成字符串
     *
     * @param date
     * @param format
     * @return
     */
    public static String convert2String(Date date, String format) {
        SimpleDateFormat formater = new SimpleDateFormat(format);
        try {
            return formater.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取时间戳
     *
     * @return
     */
    public static long getTimestamp() {
        return System.currentTimeMillis();
    }


    /**
     * 获取星期几
     *
     * @param date
     * @return
     */
    public static int getWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek - 1;
    }

    /**
     * 判断时间是否在时间段内
     *
     * @param time         System.currentTimeMillis()
     * @param strDateBegin 开始时间 00:00:00
     * @param strDateEnd   结束时间 00:05:00
     * @return
     */
    public static boolean isInDate(long time, String strDateBegin, String strDateEnd) {
        Calendar calendar = Calendar.getInstance();
        // 处理开始时间
        String[] startTime = strDateBegin.split(":");
        calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startTime[0]));
        calendar.set(Calendar.MINUTE, Integer.valueOf(startTime[1]));
        calendar.set(Calendar.SECOND, Integer.valueOf(startTime[2]));
        calendar.set(Calendar.MILLISECOND, 0);
        long startTimeL = calendar.getTimeInMillis();
        // 处理结束时间
        String[] endTime = strDateEnd.split(":");
        calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(endTime[0]));
        calendar.set(Calendar.MINUTE, Integer.valueOf(endTime[1]));
        calendar.set(Calendar.SECOND, Integer.valueOf(endTime[2]));
        calendar.set(Calendar.MILLISECOND, 0);
        long endTimeL = calendar.getTimeInMillis();
        return time >= startTimeL && time <= endTimeL;
    }

    /*
     * 返回今天 yyyy-MM-dd 00:00:00
     */
    public static Date getTodayZero() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        return cal.getTime();
    }

	public static LocalDateTime getTodayZeroLocal(){
		Date todayZero = getTodayZero();
		Instant instant = todayZero.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
		return localDateTime;
	}

    /*
     * 返回今天 yyyy-MM-dd 00:00:00
     */
    public static Date getTomorrowZero() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE,1);//这里改为1
        Date time=cal.getTime();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        return cal.getTime();
    }

    /*
     * 返回今年 yyyy-01-01 00:00:00
     */
    public static Date getYear(int year) {
        Calendar cal = Calendar.getInstance();
        cal.set(year, 0,1, 0, 0, 0);
        return cal.getTime();
    }

    public static Date getYearMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(year, month-1,1, 0, 0, 0);
        return cal.getTime();
    }
    
	/**
	 * Double/Integer/Long --> String(yyyy-MM-dd)
	 * @param time
	 * @return
	 */
	public static String dateFormat(Object time){
		if(time == null) {
			return "";
		}
		
		Long value = null;
		if(time instanceof Double) {
			value = ((Double)time).longValue();
		} else if(time instanceof Integer) {
			value = ((Integer)time).longValue();
		} else if(time instanceof BigInteger) {
			value = ((BigInteger)time).longValue();
		} else {
			value = (Long) time;
		}
		if(value.toString().length() == 10) {
			value = value*1000;
		}
		
		return dateFormat.get().format(new Date(value));
	}


	public static int betweenMins(String dateStr, String createDateStr) {
		Calendar c = Calendar.getInstance();
		try {
			c.setTime(new SimpleDateFormat(FORMAT_DTF).parse(dateStr));
			long begin = c.getTimeInMillis();
			c.setTime(new SimpleDateFormat(FORMAT_DTF).parse(createDateStr));
			long end = c.getTimeInMillis();
			return (int)((begin - end) / (1000 * 60) );
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return 0 ;
	}

	/**
	 * 从时间戳转换成 LocalDateTime
	 * @param timestamp
	 * @return
	 */
//	private static LocalDateTime timestamp(Long timestamp){
//		Date date = new Date(timestamp);
//		return LocalDateTime.ofInstant(date.toInstant(), ZoneId.of(SHORT_IDS.get("CTT")));
//	}

	/**
	 * 以second为主进行判断
	 * 以first为开始时间，second为结束时间
	 * 判断两个时间是否在通过一个周内。
	 *
	 * @param first
	 * @param second
	 */
	public static Boolean checkWeekBetween(LocalDateTime first,LocalDateTime second){
//        两个时间差不超过7天,
		Period period = Period.between(first.toLocalDate(),second.toLocalDate());
		int years = period.getYears();
		if(years > 0){
			return false;
		}
		int months = period.getMonths();
		if(months > 0){
			return false;
		}
		int days = period.getDays();
		if(days == 0){
//          表明是同一天
			return true;
		}
		if(days > 7  || days < -7){
//            两个时间差 超出了7天
			return false;
		}
		int firstDayOfWeek = first.getDayOfWeek().getValue();
		int secondDayOfWeek = second.getDayOfWeek().getValue();
		if(secondDayOfWeek == 1){
			if(oneDay(firstDayOfWeek,secondDayOfWeek,days)){
				return true;
			}else {
				return false;
			}
		}
		if(secondDayOfWeek == 7){
			if(sevenDay(firstDayOfWeek,secondDayOfWeek,days)){
				return true;
			}else {
				return false;
			}
		}
		if(otherDay(firstDayOfWeek,secondDayOfWeek,days)){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * secondDayOfWeek 是所在星期的第一天
	 * 星期的第一天 数据处理
	 * @return
	 */
	private static Boolean oneDay(int firstDayOfWeek,int secondDayOfWeek,int days){
		if(days > 0 ){
//            表明 first 比second 小 不在同一周
			return false;
		}else {
//            表明 first 比second 大
			if(secondDayOfWeek - days == firstDayOfWeek){
				return true;
			}
		}
		return false;
	}

	/**
	 * 星期的第7天的时候处理数据
	 * @return
	 */
	private static Boolean sevenDay(int firstDayOfWeek,int secondDayOfWeek,int days){
//        second 是周日
		if(firstDayOfWeek + days == secondDayOfWeek){
			return true;
		}
		return false;
	}

	/**
	 * 其他天的数据处理
	 * @return
	 */
	private static Boolean otherDay(int firstDayOfWeek,int secondDayOfWeek,int days){
		if(days < 0){
//              表明 first 比 second 大
			if((secondDayOfWeek - days) == firstDayOfWeek){
//                    两者是 一周内
				return true;
			}
		}else {
//          表明 first 比 second 小
			if(firstDayOfWeek + days == secondDayOfWeek){
				//                    两者是 一周内
				return true;
			}
		}
		return false;
	}
//    /*
//     * 返回明年 yyyy-01-01 00:00:00
//     */
//    public static String getYearTo() {
//        Calendar cal = Calendar.getInstance();
//        cal.add(Calendar.YEAR,1);//这里改为1
//        Date time=cal.getTime();
//        cal.set(cal.get(Calendar.YEAR),  0,1, 0, 0, 0);
//        Date beginOfDate = cal.getTime();
//        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        return formatter.format(beginOfDate);
//    }
}
